#ifdef __QT5_TARGET

#include <QtCore/QStringList>

#else

#include <QStringList>

#endif
#include <qdebug.h>
#include "ScheduleManager.h"
#include <QSqlQuery>
#include <QString>
#include <QVariant>
#include "CouldNotExecQueryException.h"
#include <qsqlerror.h>

ScheduleManager::ScheduleManager(void)
{
	this->thisWeek = NULL;
	this->nextWeek = NULL;
	this->lastWeek = NULL;
	this->nextWeekDates = NULL;
	this->lastWeekDates = NULL;
	this->currentWeekCache = new QMap<QDateTime*,Schedule*>();
	thisWeekDates = new QList<QDateTime*>();
	this->schedulesById = new QHash<unsigned int, Schedule*>();
	this->schedules = new QMap<QDateTime*,Schedule*>();
	this->schedulesByTimeStamp = new QMap<int, Schedule*>();
}

void ScheduleManager::deleteSchedule(Schedule* s)
{
	unsigned int start = s->getStartDate()->toTime_t();
	unsigned int end = s->getEndDate()->toTime_t();
	
	for(start;start < end; start+=900)
	{ 
		int rem4 = this->schedulesByTimeStamp->remove(start);
		qDebug() << QString::number(rem4);
	}
	
	QDateTime* startDate = s->getStartDate();
	
	int rem1 = schedules->remove(startDate);
	int rem2 = schedulesById->remove(s->getId());
	int rem3 = this->currentWeekCache->remove(startDate);

	if(s)
	{
		delete s;
	}
}

void ScheduleManager::updateSchedule(Schedule* s, const QString& note)
{
	Schedule* s2;
	foreach(s2,*this->schedulesByTimeStamp)
	{
		QString str = s2->getNote();
	}
	s->setNote(note);
	QString sql = "UPDATE RESERVATION SET NOTE = :note WHERE RESERV_ID= :reserv_id";
	QSqlQuery query;
	query.prepare(sql);
	query.bindValue(":note",note);
	query.bindValue(":reserv_id",s->getId());
	if(!query.exec())
	{
		CouldNotExecQueryException e;
		e.setMessage("Could not update the note. " + query.lastError().text());
	}
}

ScheduleManager::~ScheduleManager(void)
{
	try
	{
		if(!schedules->empty())
		{
			QMap<QDateTime*,Schedule*>::iterator it = schedules->begin();
			while(it != schedules->end())
			{
				if(it.value() != NULL)
				{
					delete it.value();
					it.value() = NULL;
				}

				if(it.key() != NULL)
				{
					//delete it.key();
				//it.key() = NULL;
				}
				it++;
			}
		}

	if(thisWeekDates != NULL)
	{
		for(int i = 0; i < thisWeekDates->count();++i)
		{
			if(thisWeekDates->at(i) != NULL)
			{
				//delete thisWeekDates->at(i);
				//thisWeekDates->at(i) = NULL;
			}
		}
		
		delete thisWeekDates;
		thisWeekDates = NULL;
	}
		
		
	if(nextWeekDates != NULL && !nextWeekDates->empty())
	{
		for(int i = 0; i < nextWeekDates->count(); ++i)
		{
			if(nextWeekDates->at(i) != NULL)
			{
				delete nextWeekDates->at(i);
				//nextWeekDates->at(i) = NULL;
			}
		}

		delete nextWeekDates;
		nextWeekDates = NULL;
	}

	if(lastWeekDates != NULL)
	{
		for(int i = 0; i < lastWeekDates->count();++i)
		{
			if(lastWeekDates->at(i) != NULL)
			{
				delete lastWeekDates->at(i);
				//lastWeekDates.at(i) = NULL;
			}
		}

		delete lastWeekDates;
		lastWeekDates = NULL;
	}

	if(thisWeek != NULL)
	{
		if(thisWeek->first != NULL)
		{
			//delete thisWeek->first;
			thisWeek->first = NULL;
		}

		if(thisWeek->second != NULL)
		{
			//delete thisWeek->second;
			thisWeek->second = NULL;
		}

		//delete thisWeek;
		thisWeek = NULL;
	}
	
	if(nextWeek != NULL)
	{
		if(nextWeek->first != NULL)
		{
			delete nextWeek->first;
			nextWeek->first = NULL;
		}

		if(nextWeek->second != NULL)
		{
			delete nextWeek->second;
			nextWeek->second = NULL;
		}

		delete nextWeek;
		nextWeek = NULL;
	}

	if(lastWeek != NULL)
	{
		if(lastWeek->first != NULL)
		{
			delete lastWeek->first;
			lastWeek->first = NULL;
		}

		if(lastWeek->second != NULL)
		{
			delete lastWeek->second;
			lastWeek->second = NULL;
		}

		delete lastWeek;
		lastWeek = NULL;
	}

	}catch(int i)
	{
		Exception e;
		e.setMessage("Fatal error: Memory corruption while deleting Schedule Manager");
		e.setErrorCode(i);
		throw e;
	}

}

Schedule* ScheduleManager::getSchedule(QDateTime date)
{
	return NULL;
}

Schedule* ScheduleManager::getNextSchedule()
{
	return NULL;
}

Schedule* ScheduleManager::getLastSchedule()
{
	return NULL;
}

QList<Schedule*> ScheduleManager::getSchedules(Patient* p)
{
	return QList<Schedule*>();
}

QList<Schedule*> ScheduleManager::getAllSchedules()
{
	return QList<Schedule*>();
}

Schedule* ScheduleManager::getScheduleByTime(unsigned int time)
{
	return this->schedulesByTimeStamp->value(time);
}

void ScheduleManager::addSchedule(Schedule* schedule)
{
	this->schedulesById->insert(schedule->getId(),schedule);
	this->schedules->insert(schedule->getStartDate(),schedule);

	unsigned int start = schedule->getStartDate()->toTime_t();
	unsigned int end = schedule->getEndDate()->toTime_t();
	for(start; start < end; start += 900)
	{
		this->schedulesByTimeStamp->insert(start, schedule);
	}
	
	if(*schedule->getStartDate() >= *thisWeek->first && *schedule->getStartDate() < *thisWeek->second)
		this->currentWeekCache->insert(schedule->getStartDate(),schedule);
	/*
	else if(*schedule->getStartDate() >= *nextWeek->first && *schedule->getStartDate() < *nextWeek->second)
		this->nextWeekCache->insert(schedule->getStartDate(),schedule);
	else if(*schedule->getStartDate() >=  *this->lastWeek->first && *schedule->getStartDate() < *this->lastWeek->second)
		this->lastWeekCache->insert(schedule->getStartDate(),schedule);
		*/
	//this->addToThisWeekDates(schedule->getStartDate());
}

QList<QDateTime*>* ScheduleManager::getThisWeekDates()
{
	if(this->thisWeekDates == NULL)
	{
		NullPointerException e;
		e.setMessage("Fatal error: Schedule buffer is null");
		throw e;
	}
	return this->thisWeekDates;
}


void ScheduleManager::addToThisWeekDates(QDateTime* date)
{
	QList<QDateTime*>::iterator it = std::lower_bound(this->thisWeekDates->begin(),this->thisWeekDates->end(),date,Utils::lessDate);
	this->thisWeekDates->insert(it,date);
}

QList<Schedule*> ScheduleManager::getSchedulesForThisWeek()
{
	return this->currentWeekCache->values();
}

QMap<QDateTime*,Schedule*>* ScheduleManager::getScheduleMapForThisWeek()
{
	QMap<QDateTime*,Schedule*>::iterator it = this->currentWeekCache->begin();
	while(it != this->currentWeekCache->end())
	{
		qDebug() << it.key()->toString();
		it++;
	}
	return this->currentWeekCache;
}

QPair<QDateTime*,QDateTime*>* ScheduleManager::getWeek(QDateTime dt)
{
	int day = dt.date().dayOfWeek() -1;
	int dayInLocale = ((day + 2 ) % 7)+1;
	QDateTime firstDay = dt.addDays(-(dayInLocale-1));
	firstDay.setTime(QTime(9,0));
	QDateTime lastDay = dt.addDays(7-dayInLocale);
	lastDay.setTime(QTime(23,30));
	return new QPair<QDateTime*,QDateTime*>(new QDateTime(firstDay),new QDateTime(lastDay));	
}

QPair<QDateTime*,QDateTime*>* ScheduleManager::getThisWeek()
{
	if(this->thisWeek != NULL)
		return thisWeek;
	QDateTime currentDate = QDateTime::currentDateTime();
	this->thisWeek = getWeek(currentDate);
	return thisWeek;
}

Schedule* ScheduleManager::getSchedule(unsigned int sched_id)
{
	return this->schedulesById->value(sched_id,NULL);
}
QPair<QDateTime*,QDateTime*>* ScheduleManager::getCurrentWeek()
{
	return this->thisWeek;
}

void ScheduleManager::setThisWeek(QPair<QDateTime *,QDateTime*>* date)
{
	this->thisWeek = date;
}

bool ScheduleManager::thisWeekLoaded()
{
	return !this->currentWeekCache->empty();
}